package com.witsoft.device.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.witsoft.device.dao.DeviceReporterDao;
import com.witsoft.device.dao.DeviceStatusTimeLineDao;
import com.witsoft.device.entity.DeviceEntity;
import com.witsoft.device.entity.DeviceReporterMonth;
import com.witsoft.device.model.DeviceRealTimeSpent;
import com.witsoft.device.model.RunAndOpenTimesAllMonth;
import com.witsoft.device.model.RunningTimesEachMonth;
import com.witsoft.device.service.DeviceReporterService;
import com.witsoft.device.service.DeviceService;
import com.witsoft.device.service.DeviceStatusTimeLineService;
import com.witsoft.device.utils.DateUtil;
import com.witsoft.device.utils.NumberUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Resource;
import java.text.DecimalFormat;
import java.util.*;


@Slf4j
@Service
public class DeviceReporterServiceImpl extends ServiceImpl<DeviceReporterDao, DeviceReporterMonth> implements DeviceReporterService {


    @Resource
    DeviceReporterDao reporterDao;

    @Resource
    private DeviceStatusTimeLineDao statusTimeLineDao;

    @Resource
    private DeviceService deviceService;

    @Resource
    private DeviceStatusTimeLineService timeLineService;


    /**
     * @desc feature(2021.12.07)：需求迭代（设备时间稼动率计算公式更改）==> 所有设备总的月度时间稼动率 = sum（单个设备稼动率）/设备数
     * @return
     */
    @Override
    public Map<String, Object> getAllDeviceMonthGrainMoveRateV2() {

        ArrayList<Object> xdatas = new ArrayList<>(12);
        ArrayList<Object> ydatas = new ArrayList<>(12);

        List<DeviceEntity> allList = deviceService.getAllList();

        //计算起始查询时间, 从当前时间往前推足够12个月份
        //Date startTime = DateUtil.getLast12MonthsDateFromNow();
        //feature(2022.04.06): 获取当年一月份到现在的时间的oee，不再是往当前时间前推12个月
        Date firstDayStampOfMonth = DateUtil.getFirstDayStampOfMonth(1);

        //获取所有设备的各个月份的时间稼动率总和
        List<RunningTimesEachMonth> timeGrainRateEachMonth = reporterDao.getSumTimeGrainRateEachMonth(firstDayStampOfMonth);

        timeGrainRateEachMonth.forEach(timeMonth ->{
            String date = timeMonth.getDate();
            Double total = timeMonth.getTotal();

            xdatas.add(date);
            ydatas.add(NumberUtil.df.format(total / allList.size()));
        });


        //start >######################## 计算当月的各个设备的时间稼动率 ################################
        String currentMonth = DateUtil.sdf.format(new Date());
        //step-1：当月月份
        Double sumTimeRateCurrentMonth = 0.0;

        //step-3: 遍历各个设备，计算当前性能的稼动率
        for (DeviceEntity device: allList) {
            //获取该设备当前月份的总运行时长
            Long deviceSumRunningMonth = reporterDao.getDeviceSumRunningMonth(device.getId());
            //获取该设备当前月份的总开机时长
            Long deviceSumOpeningMonth = reporterDao.getDeviceSumOpeningMonth(device.getId());

            if(deviceSumOpeningMonth > 0){
                Double performanceRate = 1.0 * deviceSumRunningMonth / deviceSumOpeningMonth;
                sumTimeRateCurrentMonth += performanceRate;
            }
        }

        //step-4: 计算当月的平均值
        compensateMonth(xdatas, ydatas);

        xdatas.add(currentMonth);
        ydatas.add(NumberUtil.df.format(100 * sumTimeRateCurrentMonth / allList.size()));
        //end >######################## 计算当月的各个设备的时间稼动率 ##################################


        //fixed(2021.11.08): 按12个月份，填充12个数据
        int size = 12 - ydatas.size();
        for (int i = 0; i < size; i++) {
            ydatas.add("");
        }

        Map<String, Object> data = new HashMap<>(2);
        data.put("x", xdatas);
        data.put("y", ydatas);

        return data;
    }

    /**
     * @desc 补偿计算,解决01月-当前月之间都没查到数据的问题
     * @param xdatas
     * @param ydatas
     */
    private void compensateMonth(ArrayList<Object> xdatas, ArrayList<Object> ydatas) {

        Integer currentYearNumber = DateUtil.getCurrentYearNumber();
        //为空，则补偿当前年份从1月份开始到当前月份
        if(CollectionUtils.isEmpty(xdatas)){
            Integer currentMonthNumber = DateUtil.getCurrentMonthNumber();
            for (int i = 1; i < currentMonthNumber; i++) {
                xdatas.add(currentYearNumber +"-" + i);
                ydatas.add("0");
            }
        }
    }


    /**
     * @desc feature(2021.12.07)：需求迭代（设备性能稼动率计算公式更改）==> 所有设备总的月度性能稼动率 = sum（单个设备性能稼动率）/设备数
     * @return
     */
    @Override
    public Map<String, Object> getAllDeviceMonthPerformanceGrainMoveRateV2() {

        ArrayList<Object> xdatas = new ArrayList<>(12);
        ArrayList<Object> ydatas = new ArrayList<>(12);

        List<DeviceEntity> allList = deviceService.getAllList();

        //计算起始查询时间, 从当前时间往前推足够12个月份
        //Date startTime = DateUtil.getLast12MonthsDateFromNow();
        //feature(2022.04.06): 获取当年一月份到现在的时间的oee，不再是往当前时间前推12个月，而是只统计今年1月份往后的
        Date firstDayStampOfMonth = DateUtil.getFirstDayStampOfMonth(1);

        //获取所有设备的各个月份的时间稼动率总和
        List<RunningTimesEachMonth> performanceGrainRateEachMonth = reporterDao.getSumPerformanceGrainRateEachMonth(firstDayStampOfMonth);

        performanceGrainRateEachMonth.forEach(timeMonth ->{
            String date = timeMonth.getDate();
            Double total = timeMonth.getTotal();

            xdatas.add(date);
            ydatas.add(NumberUtil.df.format(total / allList.size()));
        });


        //start >######################## 计算当月的各个设备的时间稼动率 ################################
        String currentMonth = DateUtil.sdf.format(new Date());
        //step-1：获取每个设备每个月的节拍数和报工时长乘积
        Map workReportOfYear = deviceService.getBeatMultiplyWorkReportOfYear(getDeviceCodes(allList));

        //step-2：当月月份
        Double sumPerformanceRateCurrentMonth = 0.0;

        //step-3: 遍历各个设备，计算当前性能的稼动率
        for (DeviceEntity device: allList) {
            Object res = workReportOfYear.get(device.getName());

            if(ObjectUtils.isEmpty(res)){
                Map<String, Double> result = (Map)res;
                Double beat = result.get(currentMonth);
                //获取该设备当前月份的总运行时长
                Long deviceSumRunningMonth = reporterDao.getDeviceSumRunningMonth(device.getId());
                if(deviceSumRunningMonth > 0){
                    Double performanceRate = beat / deviceSumRunningMonth;
                    sumPerformanceRateCurrentMonth += performanceRate;
                }
            }
        }

        compensateMonth(xdatas, ydatas);

        //step-4: 计算平均值
        xdatas.add(currentMonth);
        ydatas.add(NumberUtil.df.format(100 * sumPerformanceRateCurrentMonth / allList.size()));
        //end >######################## 计算当月的各个设备的时间稼动率 ##################################


        //fixed(2021.11.08): 按12个月份，填充12个数据
        int size = 12 - ydatas.size();
        for (int i = 0; i < size; i++) {
            ydatas.add("");
        }

        Map<String, Object> data = new HashMap<>(2);
        data.put("x", xdatas);
        data.put("y", ydatas);

        return data;
    }



    @Override
    public Double getAllDeviceAverageTimeGrainRateByDay() {

        List<DeviceEntity> allList = deviceService.getAllList();

        Double sumRate = 0.0;
        //获取当天最新的total_spent未被标记的开机记录，强行计算一个开机时长
        List<DeviceRealTimeSpent> openingTimeDayOfTotalSpentIsNull = statusTimeLineDao.getSumAllOpeningTimeDayOfTotalSpentIsNull();
        List<DeviceRealTimeSpent> runningTimeDayOfTotalSpentIsNull = statusTimeLineDao.getSumAllRunningTimeDayOfTotalSpentIsNull();
        //数据去重，只保留total_spent为null的最新一条值
        Map<String, DeviceRealTimeSpent> openingTime = timeLineService.distinct(openingTimeDayOfTotalSpentIsNull);
        Map<String, DeviceRealTimeSpent> runningTime = timeLineService.distinct(runningTimeDayOfTotalSpentIsNull);

        //计算各个设备当天的时间稼动率
        for (DeviceEntity device: allList) {
            int runningTimeDay = timeLineService.getSumRunningTimeDay(device.getId());
            int sumTime = timeLineService.getSumTime(device.getId());

            DeviceRealTimeSpent openSpent = openingTime.get(device.getId());
            DeviceRealTimeSpent runSpent = runningTime.get(device.getId());
            log.info("统计当天的连续运行的设备：[{}]实时开机时间：{}，连续运行的设备实时运行时间：{}", device.getName(), JSONObject.toJSONString(openSpent), JSONObject.toJSONString(runSpent));
            if(!ObjectUtils.isEmpty(openSpent)){
                //fixed(2021.12.08): 修复读取实时时间戳异常问题
                sumTime += openSpent.getRealTimeSpent().intValue();
                //v1
                //sumTime += openSpent.getTotalSpent().intValue();
            }

            if(!ObjectUtils.isEmpty(runSpent)){
                //fixed(2021.12.08): 修复读取实时时间戳异常问题
                runningTimeDay += runSpent.getRealTimeSpent();
                //v1
                //runningTimeDay += runSpent.getTotalSpent();
            }

            if(sumTime > 0){
                Double rate = 1.0 * runningTimeDay / sumTime;
                sumRate += rate;
            }
        }

        if(sumRate >= 0){
            sumRate = sumRate / allList.size();
        }
        return sumRate;
    }


    @Override
    public Long getDeviceSumOpeningMonth(String deviceId) {
        return reporterDao.getDeviceSumOpeningMonth(deviceId);
    }


    @Override
    public Long getDeviceSumRunningMonth(String deviceId) {
        return reporterDao.getDeviceSumRunningMonth(deviceId);
    }


    @Override
    public Long getAllDeviceSumOpeningMonth() {
        return reporterDao.getAllDeviceSumOpeningMonth();
    }


    @Override
    public Long getAllDeviceSumRunningMonth() {
        return reporterDao.getAllDeviceSumRunningMonth();
    }


    /**
     * @desc 获取所有设备当前月份的性能稼动率
     * @return
     */
    @Override
    public Map<String, Object> getAllDeviceMonthPerformanceGrainMoveRate() {
        DecimalFormat df = new DecimalFormat("#");
        //当前月份
        Long allDeviceSumRunningMonth = reporterDao.getAllDeviceSumRunningMonth();

        List<String> xdatas = new ArrayList<>(12);
        List<String> ydatas = new ArrayList<>(12);

        List<DeviceEntity> allList = deviceService.getAllList();
        Map beatMultiplyWorkReportOfYear = deviceService.getBeatMultiplyWorkReportOfYear(getDeviceCodes(allList));
        Map<String, Double> totalNumByMonth = getTotalNumByMonth(allList, beatMultiplyWorkReportOfYear);

        //查询当前月之前的所有月份的设备信息
        List<RunAndOpenTimesAllMonth> andRunningMonthBefore = reporterDao.getAllDeviceSumOpeningAndRunningMonthBefore();
        for(RunAndOpenTimesAllMonth andOpenTimesAllMonth : andRunningMonthBefore){

            Long runningTimes = andOpenTimesAllMonth.getRunningTimes();

            //获取当月所有设备的节拍数与有效产品数的乘积
            Double sum = totalNumByMonth.get(andOpenTimesAllMonth.getDate());

            //记录月份
            xdatas.add(andOpenTimesAllMonth.getDate());

            //非空判断
            if(ObjectUtils.isEmpty(sum) || runningTimes <= 0){
                ydatas.add("0");
                //跳过当前循环，进入下一个
                continue;
            }

            //正确计算当前月之前的每一个月的指标
            Double rate = 1.0 * sum / runningTimes;
            ydatas.add(df.format(rate * 100));
        }


        //计算当前月的
        String nowMonth = DateUtil.sdf.format(new Date());
        Double nowMonthSum = totalNumByMonth.get(nowMonth);
        if(allDeviceSumRunningMonth <= 0){
            ydatas.add("0");
        }else{
            Double rate = 1.0 * nowMonthSum / allDeviceSumRunningMonth;
            ydatas.add(df.format(rate * 100));
        }

        //ydatas进行排序

        //fixed(2121.11.08)：按12个月份，填充12个数据
        if(ydatas.size() < 12){
            int size = 12 - ydatas.size();
            for (int i = 0; i < size; i++) {
                ydatas.add("");
            }
        }

        Map<String, Object> data = new HashMap<String, Object>();
        data.put("x", xdatas);
        data.put("y", ydatas);
        return data;
    }


    private Map<String, Double> getTotalNumByMonth(List<DeviceEntity> allList, Map beatMultiplyWorkReportOfYear){

        Map<String, Double> data = new HashMap<>();

        //便利设备列表
        allList.forEach(deviceEntity -> {
            //获取该设备12个月各个月的总的节拍与有效生产产品总数
            Object res = beatMultiplyWorkReportOfYear.get(deviceEntity.getName());
            if(!ObjectUtils.isEmpty(res)){
                Map result = (Map) res;
                //便利每个月的的节拍与有效生产产品总数
                result.keySet().forEach(key ->{
                    Double num = (Double) result.get(key);

                    //将每个设备相同月份的num进行累加
                    if(!data.containsKey(key)){
                        data.put(key.toString(), num);
                    }else {
                        Double value = data.get(key);
                        value += num;
                        data.put(key.toString(), value);
                    }
                });
            }

        });

        return data;
    }


    @Override
    public String getDeviceCodes(List<DeviceEntity> list){

        StringBuffer codes = new StringBuffer();
        list.forEach(deviceEntity -> {
            codes.append(deviceEntity.getName()).append(",");
        });

        String deviceCodes = codes.substring(0, codes.length() - 1);
        return deviceCodes;
    }


    /**
     * @desc 获取所有设备当前月份的稼动率
     * @return
     */
    @Override
    public Map<String, Object> getAllDeviceMonthGrainMoveRate() {

        DecimalFormat df = new DecimalFormat("#");

        //当前月份
        Long allDeviceSumOpeningMonth = reporterDao.getAllDeviceSumOpeningMonth();
        Long allDeviceSumRunningMonth = reporterDao.getAllDeviceSumRunningMonth();
        List<String> xdatas = new ArrayList<>(12);
        List<String> ydatas = new ArrayList<>(12);

        List<RunAndOpenTimesAllMonth> andRunningMonthBefore = reporterDao.getAllDeviceSumOpeningAndRunningMonthBefore();
        for(RunAndOpenTimesAllMonth andOpenTimesAllMonth : andRunningMonthBefore){

            Long openTimes = andOpenTimesAllMonth.getOpenTimes();
            Long runningTimes = andOpenTimesAllMonth.getRunningTimes();
            //记录月份
            xdatas.add(andOpenTimesAllMonth.getDate());

            //非空判断
            if(openTimes <= 0){
                ydatas.add("0");
                //跳过当前循环，进入下一个
                continue;
            }

            //正确计算当前月之前的每一个月的指标
            Double rate = 1.0 * runningTimes / openTimes;
            ydatas.add(df.format(rate * 100));
        }



        //定时任务每月一号执行统计上个月的报表任务（统计不到当月的），所有这里要单独计算当月的报表指标
        xdatas.add(DateUtil.sdf.format(new Date()));
        //计算当前月份的指标
        if(allDeviceSumOpeningMonth <= 0){
            ydatas.add("0");
        }else{
            Double rate = 1.0 * allDeviceSumRunningMonth / allDeviceSumOpeningMonth;
            ydatas.add(df.format(rate * 100));
        }


        //fixed(2121.11.08)：按12个月份，填充12个数据
        if(ydatas.size() < 12){
            int size = 12 - ydatas.size();
            for (int i = 0; i < size; i++) {
                ydatas.add("");
            }
        }

        Map<String, Object> data = new HashMap<String, Object>();
        data.put("x", xdatas);
        data.put("y", ydatas);

        return data;
    }
}
